<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ganttComponent</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        html,
        body {
            width: 100%;
            height: 100%;
            overflow: hidden;
            overflow: auto;
        }

        .gantt-box {
            margin: 0 20px;
            position: relative;
            width: 100%;
            height: 100%;
        }

        #timer {
            position: absolute;
            top: 0;
            left: 0;
            padding: 10px;
            background: rgba(255, 255, 255, 0.8);
            z-index: 1000;
        }

        #controls {
            margin-top: 10px;
        }

        #movingIcon {
            position: absolute;
            width: 2px;
            background: red;
            z-index: 999;
        }
    </style>
    <!-- 引入 EasyUI CSS -->
    <link rel="stylesheet" type="text/css" href="https://www.jeasyui.com/easyui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="https://www.jeasyui.com/easyui/themes/icon.css">
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.min.css">
    <!-- 引入 EasyUI JavaScript -->
    <script type="text/javascript" src="https://www.jeasyui.com/easyui/jquery.min.js"></script>
    <script type="text/javascript" src="https://www.jeasyui.com/easyui/jquery.easyui.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/luxon@1.27.0/build/global/luxon.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.0.0"></script>
</head>

<body>
    <div id="ganttComponent">
        <div id="timer">
            <div id="timerShow">2023-10-01</div>
            <div id="controls">
                <button id="startButton">开始</button>
                <button id="pauseButton">暂停</button>
                <button id="resetButton">重置</button>
            </div>
        </div>
        <div style="width: 100%; height: 100%;">
            <canvas id="ganttChart"></canvas>
            <div id="movingIcon"></div>
        </div>
    </div>

    <script type="module">
        // 初始化 DataGrid
        const initTasks = [
            {
                name: '框柱安装1组', color: 'rgba(255, 99, 132, 0.2)',
                meshs: [
                    { name: '1', timestamp: 1676248341000 },
                    { name: '2', timestamp: 1676255541000 },
                    { name: '3', timestamp: 1676262741000 },
                    { name: '4', timestamp: 1676269941000 },
                    { name: '5', timestamp: 1676277141000 },
                    { name: '6', timestamp: 1676284341000 },
                    { name: "7", timestamp: 1676334741000 },
                    {
                        "name": "8",
                        "timestamp": 1676341941000
                    },
                    {
                        "name": "9",
                        "timestamp": 1676349141000
                    },
                    {
                        "name": "10",
                        "timestamp": 1676356341000
                    },
                    {
                        "name": "11",
                        "timestamp": 1676363541000
                    },
                    {
                        "name": "12",
                        "timestamp": 1676370741000
                    }
                ]
            },
            {
                name: '框柱安装2组', color: 'rgba(54, 162, 235, 0.2)',
                meshs: [
                    { name: '13', timestamp: 1676421141000 },
                    { name: '14', timestamp: 1676431141000 },
                    { name: '15', timestamp: 1676441141000 },
                    { name: '16', timestamp: 1676451141000 },
                    { name: '17', timestamp: 1676461141000 },
                    { name: '18', timestamp: 1676471141000 },
                    { name: '19', timestamp: 1676334741000 },
                    { name: '20', timestamp: 1676344741000 },
                    { name: '21', timestamp: 1676354741000 },
                    { name: '22', timestamp: 1676364741000 },
                    { name: '23', timestamp: 1676374741000 },
                    { name: '24', timestamp: 1676384741000 }
                ]
            },
            {
                name: '框柱安装3组', color: 'rgba(255, 206, 86, 0.2)',
                meshs: [
                    { name: '25', timestamp: 1676593941000 },
                    { name: '26', timestamp: 1676603941000 },
                    { name: '27', timestamp: 1676613941000 },
                    { name: '28', timestamp: 1676623941000 },
                    { name: '29', timestamp: 1676633941000 },
                    { name: '30', timestamp: 1676643941000 },
                    { name: '31', timestamp: 1676513941000 },
                    { name: '32', timestamp: 1676523941000 },
                    { name: '33', timestamp: 1676533941000 },
                    { name: '34', timestamp: 1676543941000 },
                    { name: '35', timestamp: 1676553941000 },
                    { name: '36', timestamp: 1676563941000 }
                ]
            }
        ];

        let initialTasks = initTasks.map(task => {
            return updateTaskDates(task);
        });
        let tasksData = [];

        $(document).ready(function () {
            // 初始化甘特图
            const ctx = document.getElementById('ganttChart').getContext('2d');
            let ganttChart;

            function initGanttChart(tasks) {
                if (ganttChart) {
                    ganttChart.destroy(); // 销毁旧的图表实例
                }
                ganttChart = new Chart(ctx, {
                    type: 'bar',
                    data: {
                        labels: tasks.map(task => task.name),
                        datasets: [{
                            label: '任务进度',
                            data: tasks.map(task => ({})),
                            backgroundColor: [],
                            borderColor: [],
                            borderWidth: 0
                        }]
                    },
                    options: {
                        indexAxis: 'y',
                        aspectRatio: false,    // 宽度自适应
                        scales: {
                            x: {
                                type: 'time',
                                time: {
                                    unit: 'day',
                                    tooltipFormat: 'yyyy-MM-dd'
                                },
                                min: getMinDate(tasks),
                                max: getMaxDate(tasks)
                            },
                            y: {
                                ticks: {
                                    autoSkip: false
                                }
                            }
                        },
                        plugins: {
                            legend: {
                                display: false
                            },
                            title: {
                                display: true,
                                text: '横道图示例'
                            }
                        },
                        elements: {
                            bar: {
                                display: false
                            }
                        }
                    },
                    plugins: [{
                        id: 'customGantt',
                        afterDraw: function (chart) {
                            const ctx = chart.ctx;
                            const xScale = chart.scales.x;
                            const yScale = chart.scales.y;

                            tasks.forEach((task, index) => {
                                const startDate = task.meshs.reduce((min, mesh) => {
                                    const start = luxon.DateTime.fromMillis(mesh.timestamp);
                                    return start < min ? start : min;
                                }, luxon.DateTime.fromMillis(task.meshs[0].timestamp));

                                const endDate = startDate.plus({ days: task.Duration });

                                const x = xScale.getPixelForValue(startDate);
                                const y = yScale.getPixelForValue(task.name) - 12;
                                const width = xScale.getPixelForValue(endDate) - x;
                                const height = 24;

                                ctx.fillStyle = task.color;
                                ctx.fillRect(x, y, width, height);

                                ctx.fillStyle = '#000';
                                ctx.font = '12px Arial';
                                ctx.textAlign = 'center';
                                ctx.fillText(task.name, x + width / 2, y + height / 2 + 4);
                            });
                        }
                    }]
                });
            }

            // 初始化时间轴
            const movingIcon = document.getElementById('movingIcon');
            const timerElement = document.getElementById('timerShow');
            let currentDate;
            let isRunning = false;
            let timerInterval;
            let compMeshs = [];
            let meshShowIndex = 0;

            function initTimer(tasks) {
                currentDate = luxon.DateTime.fromISO(getMinDate(tasks));
                timerElement.textContent = currentDate.toFormat('yyyy-MM-dd');
                updateMovingIcon();
            }

            function updateTimer(tasks) {
                currentDate = currentDate.plus({ minutes: 10 });
                if (currentDate.ts > luxon.DateTime.fromISO(getMaxDate(tasks)).ts) {
                    initTimer(tasks);
                    return;
                }
                timerElement.textContent = currentDate.toFormat('yyyy-MM-dd');

                // 让太阳光源围绕场景旋转
                const time = (currentDate.ts / 86400000) * Math.PI * 2 + 0.35;
                const radius = 100; // 旋转半径
                // sunLight.position.x = Math.cos(time) * radius; // X 轴旋转
                // sunLight.position.z = Math.sin(time) * radius; // Z 轴旋转
                // sunLight.position.y = Math.sin(time) * radius;
                // console.log(time)
                // sunLight.update();

                updateMovingIcon();  // 更新移动图标位置
                updateMeshVisible();  // 更新组件可见性
            }

            function updateMeshVisible() {
                if (compMeshs[0] && currentDate.ts > compMeshs[0].timestamp) {
                    meshs.forEach(mesh => {
                        if (mesh.name === compMeshs[0].name) {
                            mesh.visible = true
                        }
                    })
                    compMeshs.shift()
                    console.log(compMeshs)
                }
            }

            function updateMovingIcon() {
                if (!ganttChart) return;
                const chart = ganttChart;
                const xScale = chart.scales.x;
                const x = xScale.getPixelForValue(currentDate.ts);
                movingIcon.style.left = `${x - 1}px`;
                movingIcon.style.top = `${chart.chartArea.top}px`;
                movingIcon.style.height = `${chart.chartArea.height + 10}px`;
            }

            function getMinDate(tasks) {
                return tasks.reduce((min, task) => {
                    const start = luxon.DateTime.fromISO(task.StartDate).minus({ days: 1 });
                    return start < min ? start : min;
                }, luxon.DateTime.fromISO(tasks[0].StartDate).minus({ days: 1 })).toISODate();
            }

            function getMaxDate(tasks) {
                return tasks.reduce((max, task) => {
                    const end = luxon.DateTime.fromISO(task.StartDate).plus({ days: task.Duration + 2 });
                    return end > max ? end : max;
                }, luxon.DateTime.fromISO(tasks[0].StartDate).plus({ days: tasks[0].Duration + 2 })).toISODate();
            }

            // 初始化甘特图和时间轴
            initGanttChart(initialTasks);
            initTimer(initialTasks);

            // 绑定按钮事件
            const startButton = document.getElementById('startButton');
            const pauseButton = document.getElementById('pauseButton');
            const resetButton = document.getElementById('resetButton');

            startButton.addEventListener('click', function () {
                if (!isRunning) {
                    timerInterval = setInterval(() => updateTimer(initialTasks), 10);
                    isRunning = true;
                }
            });

            pauseButton.addEventListener('click', function () {
                if (isRunning) {
                    clearInterval(timerInterval);
                    isRunning = false;
                }
            });

            resetButton.addEventListener('click', function () {
                clearInterval(timerInterval);
                initTimer(initialTasks);
                isRunning = false;
                meshs.forEach(mesh => {
                    mesh.visible = false;
                });
                compMeshs = new Array();
                meshShowIndex = 0
                initialTasks.forEach(task => {
                    task.meshs.forEach(mesh => {
                        compMeshs.push(mesh)
                    })
                });

                compMeshs.forEach(mesh => {
                    if (typeof mesh.timestamp !== "number") { mesh.timestamp = luxon.DateTime.fromFormat(mesh.timestamp, 'MM/dd/yyyy HH:mm:ss').ts }
                });

                compMeshs.sort((a, b) => {
                    return a.timestamp - b.timestamp;
                });
            });
        });

        function updateTaskDates(task) {
            if (!task.meshs || task.meshs.length === 0) {
                task.StartDate = '';
                task.Duration = '';
                return;
            }

            const dates = task.meshs.map(mesh => mesh.timestamp);
            const minDate = luxon.DateTime.fromMillis(
                dates.reduce((min, date) => date < min ? date : min)
            );
            const maxDate = luxon.DateTime.fromMillis(
                dates.reduce((max, date) => date > max ? date : max)
            );

            task.StartDate = minDate.toISODate();
            task.Duration = maxDate.diff(minDate, 'days').days;
            return task;
        }
    </script>
</body>

</html>